/* eslint-disable no-undef */
"use strict"
import manifest from "@/manifest.json"
import config from "@/config"

export default class Update {
  constructor(option = {}) {
    this.isInit = option.isInit || false
    this.updateInfoKey = option.updateInfoKey || "__update_info__"
    this.checkUpdateUrl = option.checkUpdateUrl || `${config.baseUrl}/app/upgrade`
    this.device = null
    this.updateInfo = null
    this.tempFilePath = null
    this.downloading = false
    this.downloadTask = null
    this.downloadProgress = 0
    this.downloadedSize = 0
    this.packageFileSize = 0

    this.installed = false
    this.installing = false

    this.isInit && this.init()
  }

  /**
   * @description 检测更新
   */
  checkAppUpdate() {
    this.getDeviceInfo((deviceInfo) => {
      console.log(deviceInfo)
      this.device = deviceInfo
      uni.request({
        url: this.checkUpdateUrl,
        data: deviceInfo,
        method: "POST",
        success: (res) => {
          console.log(res.data)
          if (res.data.data.version) {
            let updateInfo = res.data.data.version
            let installType = updateInfo.installType
            let versionCompareResult = this.versionCompare(updateInfo.versionOut, this.device.version)
            if (versionCompareResult == 1) {
              // apk
              if (installType === "apk" && deviceInfo.platform == "android") {
                uni.setStorageSync(this.updateInfoKey, updateInfo)
                if (updateInfo.silenceUpdate == 1) {
                  this.silenceUpdate(updateInfo)
                  return
                }
                if (updateInfo.forcedUpdate == 1) {
                  uni.navigateTo({
                    url: "/components/upgrade-popup/upgrade-popup",
                    fail: (err) => {
                      console.error("更新弹框跳转失败", err)
                    }
                  })
                  return
                }
                uni.navigateTo({
                  url: "/components/upgrade-popup/upgrade-popup",
                  fail: (err) => {
                    console.error("更新弹框跳转失败", err)
                  }
                })
              }
              // wgt
              if (installType === "wgt") {
                uni.setStorageSync(this.updateInfoKey, updateInfo)
                if (updateInfo.silenceUpdate == 1) {
                  this.silenceUpdate(updateInfo)
                  return
                }
                if (updateInfo.forcedUpdate == 1) {
                  uni.navigateTo({
                    url: "/components/upgrade-popup/upgrade-popup",
                    fail: (err) => {
                      console.error("更新弹框跳转失败", err)
                    }
                  })
                  return
                }
                uni.navigateTo({
                  url: "/components/upgrade-popup/upgrade-popup",
                  fail: (err) => {
                    console.error("更新弹框跳转失败", err)
                  }
                })
              }
            }
          } else {
            console.log(res)
          }
        },
        fail: (err) => {
          console.log(err)
        }
      })
    })
  }

  /**
   * @description 静默更新
   * @param {Object} updateInfo 更新信息
   */
  silenceUpdate(updateInfo) {
    let requiredKey = ["version", "downloadUrl", "installType"]
    for (let key in updateInfo) {
      if (requiredKey.indexOf(key) !== -1 && !updateInfo[key]) {
        console.error(`参数 ${key} 必填，请检查后重试`)
        uni.navigateBack()
        return
      }
    }
    this.updateInfo = updateInfo
    const versionCompareResult = this.versionCompare(updateInfo.versionOut, this.device.version)
    if (versionCompareResult == 1) {
      uni.downloadFile({
        url: this.updateInfo.downloadUrl,
        success: (res) => {
          if (res.statusCode == 200) {
            this.tempFilePath = res.tempFilePath
            plus.runtime.install(
              this.tempFilePath,
              {
                force: true
              },
              (success) => {
                if (this.tempFilePath) this.tempFilePath = null
                uni.removeStorageSync(this.updateInfoKey)
              },
              (error) => {
                console.log(error)
              }
            )
          }
        },
        fail: (err) => {
          console.log(err)
        }
      })
    }
  }

  /**
   * @description 手动更新
   * @param {Object} updateInfo 更新信息
   */
  manualUpdate() {
    if (this.downloading) {
      uni.showToast({
        mask: true,
        icon: "none",
        title: "下载中...",
        duration: 1500
      })
      return
    }

    let requiredKey = ["version", "downloadUrl", "installType"]
    for (let key in this.updateInfo) {
      if (requiredKey.indexOf(key) !== -1 && !this.updateInfo[key]) {
        console.error(`参数 ${key} 必填，请检查后重试`)
        uni.navigateBack()
        return
      }
    }
    const versionCompareResult = this.versionCompare(this.updateInfo.versionOut, this.device.version)
    if (versionCompareResult == 1) {
      this.downloading = true
      this.downloadTask = uni.downloadFile({
        url: this.updateInfo.downloadUrl,
        success: (res) => {
          if (res.statusCode == 200) {
            this.installing = true
            this.tempFilePath = res.tempFilePath
            plus.runtime.install(
              this.tempFilePath,
              {
                force: true
              },
              (success) => {
                if (this.tempFilePath) this.tempFilePath = null
                this.installed = true
                this.installing = false
                uni.removeStorageSync(this.updateInfoKey)
                if (this.updateInfo.installType == "wgt") {
                  uni.showToast({
                    title: "应用更新成功,应用即将重启",
                    mask: true,
                    icon: "none",
                    duration: 2000
                  })
                  setTimeout(() => {
                    this.downloading = false
                    this.downloadProgress = 0
                    plus.runtime.restart()
                  }, 2000)
                }
              },
              (error) => {
                console.log(error)
              }
            )
          } else {
            console.log(err)
          }
        },
        complete: () => {
          this.downloadedSize = 0
          this.packageFileSize = 0
          this.downloadTask = null
        },
        fail: (err) => {
          console.log(err)
        }
      })

      this.downloadTask.onProgressUpdate((progress) => {
        this.downloadProgress = progress.progress
        this.downloadedSize = (progress.totalBytesWritten / Math.pow(1024, 2)).toFixed(2)
        this.packageFileSize = (progress.totalBytesExpectedToWrite / Math.pow(1024, 2)).toFixed(2)
      })
    } else {
      uni.showToast({
        mask: true,
        icon: "none",
        duration: 3000,
        title: "当前已经是最新版本"
      })
    }
  }

  /**
   * @description 初始化
   */
  init() {
    this.getDeviceInfo((deviceInfo) => {
      this.device = deviceInfo
      this.updateInfo = uni.getStorageSync(this.updateInfoKey)
      if (!localPackageInfo) {
        console.error("安装包信息为空，请检查后重试")
        uni.navigateBack()
        return
      }

      let requiredKey = ["version", "downloadUrl", "installType"]
      for (let key in localPackageInfo) {
        if (requiredKey.indexOf(key) !== -1 && !localPackageInfo[key]) {
          console.error(`参数 ${key} 必填，请检查后重试`)
          uni.navigateBack()
          return
        }
      }
    })
  }

  /**
   * @description 关闭更新
   */
  async closeUpdate() {
    if (this.downloading) {
      if (this.isForcedUpdate) {
        return uni.showToast({
          title: "下载中，请稍后……",
          icon: "none",
          duration: 500
        })
      }
      uni.showModal({
        title: "是否取消下载?",
        cancelText: "否",
        confirmText: "是",
        success: (res) => {
          if (res.confirm) {
            this.downloadTask && this.downloadTask.abort()
            uni.navigateBack()
          }
        }
      })
      return
    }
    uni.navigateBack()
  }

  /**
   * @description 对比版本号，如需要，请自行修改判断规则
   * @description 支持比对	("3.0.0.0.0.1.0.1", "3.0.0.0.0.1")	("3.0.0.1", "3.0")	("3.1.1", "3.1.1.1") 之类的
   * @param {String} v1 版本号
   * @param {String} v2 版本号
   * * v1 > v2 return 1
   * v1 < v2 return -1
   * v1 == v2 return 0
   */
  versionCompare(v1 = "0", v2 = "0") {
    v1 = String(v1).split(".")
    v2 = String(v2).split(".")
    const minVersionLens = Math.min(v1.length, v2.length)

    let result = 0
    for (let i = 0; i < minVersionLens; i++) {
      const curV1 = Number(v1[i])
      const curV2 = Number(v2[i])

      if (curV1 > curV2) {
        result = 1
        break
      } else if (curV1 < curV2) {
        result = -1
        break
      }
    }

    if (result === 0 && v1.length !== v2.length) {
      const v1BiggerThenv2 = v1.length > v2.length
      const maxLensVersion = v1BiggerThenv2 ? v1 : v2
      for (let i = minVersionLens; i < maxLensVersion.length; i++) {
        const curVersion = Number(maxLensVersion[i])
        if (curVersion > 0) {
          v1BiggerThenv2 ? (result = 1) : (result = -1)
          break
        }
      }
    }

    return result
  }

  /**
   * @description 获取设备信息
   * @param {Function} callback 回调函数
   */
  getDeviceInfo(callback = () => {}) {
    let device = {}
    // 开发环境和生产环境判断
    let env = null
    // #ifdef MP-WEIXIN
    env = uni.getAccountInfoSync().miniProgram.envVersion // 获取微信运行环境
    // #endif
    // #ifndef MP-WEIXIN
    env = process.env.NODE_ENV // 获取除了微信以外的运行环境
    // #endif
    uni.getSystemInfoSync({
      success: (systemInfo) => {
        Object.assign(device, {
          env
        })
        Object.assign(device, systemInfo)
        plus.runtime.getProperty(plus.runtime.appid, (widgetInfo) => {
          Object.assign(device, widgetInfo)
          plus.device.getInfo({
            success: (info) => {
              Object.assign(device, info)
              device.appid = manifest.appid
              callback(device)
            }
          })
        })
      }
    })
  }
}
